package com.weixin.controller;


import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.wechat.pay.contrib.apache.httpclient.WechatPayHttpClientBuilder;
import com.wechat.pay.contrib.apache.httpclient.WechatPayUploadHttpPost;
import com.wechat.pay.contrib.apache.httpclient.auth.PrivateKeySigner;
import com.wechat.pay.contrib.apache.httpclient.auth.ScheduledUpdateCertificatesVerifier;
import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Credentials;
import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Validator;
import com.weixin.po.App;
import okhttp3.HttpUrl;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.http.HttpEntity;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.crypto.Cipher;
import javax.security.cert.X509Certificate;
import java.io.*;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Base64;

import static org.apache.http.entity.ContentType.APPLICATION_JSON;

/**
 * @author lmh
 * @Description:
 * @date 2021/12/24 14:11
 */

@RestController
public class testController {
    @Resource
    private App app;
    //httpclient请求
    private CloseableHttpClient httpClient;
    //私钥
    PrivateKey merchantPrivateKey = null;
    //测试ScheduledUpdateCertificatesVerifier的verify方法参数
    private ScheduledUpdateCertificatesVerifier verifier;

    String schema = "WECHATPAY2-SHA256-RSA2048";
    HttpUrl httpurl = HttpUrl.parse("https://api.mch.weixin.qq.com/v3/certificates");

    String getToken(String method, HttpUrl url, String body){
        String nonceStr = null;
        long timestamp = 0;
        String signature = null;
        try {
            nonceStr = "593BEC0C930BF1AFEB90B4A08C8FB242";
            timestamp = System.currentTimeMillis() / 1000;
            String message = buildMessage(method, url, timestamp, nonceStr, body);
            System.out.println(message);
            signature = sign(message.getBytes("utf-8"));
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return "mchid=\"" + 1552062431 + "\","
                + "nonce_str=\"" + nonceStr + "\","
                + "timestamp=\"" + timestamp + "\","
                + "serial_no=\"" + "7FAAF5C816F8DE7BCB5B247D4B60B5A04446E803" + "\","
                + "signature=\"" + signature + "\"";
    }

    String sign(byte[] message) {
        Signature sign = null;
        String s = null;
        try {
            PrivateKey privateKey = this.getPrivateKey();
            sign = Signature.getInstance("SHA256withRSA");
            sign.initSign(privateKey);
            sign.update(message);
            s = Base64.getEncoder().encodeToString(sign.sign());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return s;
    }

    String buildMessage(String method, HttpUrl url, long timestamp, String nonceStr, String body) {
        String canonicalUrl = url.encodedPath();
        if (url.encodedQuery() != null) {
            canonicalUrl += "?" + url.encodedQuery();
        }

        return method +"\n"
                + canonicalUrl+ "\n"
                + timestamp + "\n"
                + nonceStr + "\n"
                + body + "\n";
    }
/**
 * @Decription  获取微信支付平台证书
 * @Param   null
 * @Return  java.lang.String
 * @Author  lmh
 * @Date    2021/12/29 16:33
 */
    @GetMapping("/test")
    public String getCertByAPI() {
        String bodyAsString = null;
        try {
            //httpClient = this.getHttpClient();
            String token = this.getToken("GET", httpurl, "");
            //创建http请求
            URIBuilder uriBuilder = new URIBuilder("https://api.mch.weixin.qq.com/v3/certificates");
            HttpGet httpGet = new HttpGet(uriBuilder.build());
            //头部携带的信息
            httpGet.addHeader("Authorization",schema+" "+token);
            httpGet.addHeader("Accept", "application/json");
            httpGet.addHeader("User-Agent","Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36");      //PostmanRuntime/7.28.4
            //设置请求器配置：如超时限制
            RequestConfig config = RequestConfig.custom().setSocketTimeout(3 * 1000).setConnectTimeout(3 * 1000).build();
            httpGet.setConfig(config);
            //构造httpClients
            httpClient = HttpClients.createDefault();
            CloseableHttpResponse response = httpClient.execute(httpGet);
            int statusCode = response.getStatusLine().getStatusCode();
            bodyAsString = EntityUtils.toString(response.getEntity());
            System.out.println("bodyString:"+bodyAsString);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return bodyAsString;
    }

    public CloseableHttpClient getHttpClient() {
        try {
            //获取私钥
            merchantPrivateKey = this.getPrivateKey();
            //使用自动更新的签名验证器，不需要传入证书
            verifier = new ScheduledUpdateCertificatesVerifier(
                new WechatPay2Credentials("1552062431", new PrivateKeySigner("7FAAF5C816F8DE7BCB5B247D4B60B5A04446E803", merchantPrivateKey)),
                "d6f54dc2e6dc46a58e0eb9948beb30df".getBytes(StandardCharsets.UTF_8));
            // 通过WechatPayHttpClientBuilder构造的HttpClient，会自动的处理签名和验签，并进行证书自动更新
            httpClient = WechatPayHttpClientBuilder.create()
                    .withMerchant("1552062431", "7FAAF5C816F8DE7BCB5B247D4B60B5A04446E803", merchantPrivateKey)
                    //.withValidator(response -> true) // NOTE: 设置一个空的应答签名验证器，**不要**用在业务请求
                    .withValidator(new WechatPay2Validator(verifier))
                    .build();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return httpClient;
    }

    /**
     * 获取私钥。
     *filename 私钥文件路径  (required)
     * @return 私钥对象
     */
    public PrivateKey getPrivateKey() {
        PrivateKey generatePrivate = null;
        String content = null;
        try {
            content = new String(Files.readAllBytes(Paths.get("E:\\1552062431_20211207_cert\\apiclient_key.pem")), "utf-8");
            String privateKey = content.replace("-----BEGIN PRIVATE KEY-----", "")
                    .replace("-----END PRIVATE KEY-----", "")
                    .replaceAll("\\s+", "");

            KeyFactory kf = KeyFactory.getInstance("RSA");
            generatePrivate = kf.generatePrivate(
                    new PKCS8EncodedKeySpec(Base64.getDecoder().decode(privateKey)));
        } catch (Exception e) {
            throw new RuntimeException("当前Java环境不支持RSA", e);
        }
        return generatePrivate;
    }

    /**
     * @Decription 商户进件接口
     * @Param   null
     * @Return  org.springframework.http.ResponseEntity<java.lang.String>
     * @Author  lmh
     * @Date    2021/12/30 18:19
     */
    @RequestMapping("/read")
    public ResponseEntity<String> readAppProperties() {
        CloseableHttpResponse response = null;
        String bodyAsString = null;
        try {
            merchantPrivateKey = this.getPrivateKey();
            CloseableHttpClient httpClient = this.getHttpClient();
            //商户进件的接口地址
            HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/applyment4sub/applyment/");
            //设置相关请求头信息
            httpPost.addHeader("Accept", "application/json");
            httpPost.addHeader("Content-type","application/json; charset=utf-8");
            //微信平台证书序列号，不是商户证书
            httpPost.addHeader("Wechatpay-Serial","7D200113C91B6FF28A083D163B2005BA11F4BB57");

            ObjectMapper objectMapper = new ObjectMapper();
            ObjectNode rootNode = objectMapper.createObjectNode();  //根节点

            rootNode.put("business_code","1900013511_10005");   //业务申请编号
            //超级管理员
            rootNode.putObject("contact_info")
                        .put("contact_name","EKA/x3Hy3o5D2tBgAP+7iwPsh0NeMSG/qbrEVNCd9FZBp83pgHapKB1A378a2uY90HA+jdFKlig6Yp8ESjFTVyZoZ6r4+aL/UriQwAdo6Syo69mfgOkeqiWUlTt5/G3ijXrBzBf12pW32e+PvM8olgGzl3d3y33NhU21WiCdD+IQy2KJhlXIct+3sTEslGcT8pFIqzu7I9GVncNnkFQ9MhPkx3oAOontOTKMBn9h7cCn4K0apF9KNOFcwUKL02FDXStj9zNPoOD03G+5kneC48w8Y2M6cT+wd68m7ClGkpyCt1TT/fq6HHKY/laUebSgQxfwlItPioaXgVhcM0k+xg==")
                        .put("contact_id_number","dOa5z31NxxqCijZrAYLFhSx5okwi6hqHK7WXYPRaZL27+zP8y24PWfQerm3VV5oAbtxQqpryyhsnIa62P9hfoqwaG0lQ7+O7GoaK1Bj9ulmVUEm4tgGeR7U/HkLol+VpXUMShUQa9uIqEC+80hnMd7eWUAMeFaLpYcZRxlIU+uX2Oiqd3RF37FGZqY1NTTzU9JSgozzLd8Ee3k2780SzJINrKmGtJz52xgIM97HqyFYmaYi8rcpMe/vGTQT+tpDxhKWeRrVpXJ1SL7reJ81g9Zco+O/gwN9VCLcNv+awYMYczL6o3ihD3Ig2i2nWjKAEIka+s+IQX5RiegXn4GkaEA==")
                        .put("mobile_phone","FtFnij57fAO9CwkyzBb6jGT8G0bJIBT3ZqBeEyq0lp1xVLy5Co+SW9tiU0S3G7LIg/fYZcYS1Etavx7adwrqEPuN1S9188YtHHscmweJzqQKytTVgttlacqmmDnKXfcW1YoUMsCMYDpWb4gxA8iksH4TvztCDSh01Bk2w0RQjeBUjpVI15d8dtzkj1bxBadP3P1C1j3r+gWh9vWnpT88WMf1e3beFHO6LK6k8IcFkGu0RZRWGM8Y3burxQRHqIA8L6yWpxmJ+Hb9ne0yqO9Uibee3s6qtU/aVBcBAlPicr5RCAhzlZ6Cl7XLJTOiyg9VHlHsJB53OyHKVkwiCwy4Xg==")
                        .put("contact_email","Yo1dDSuNfY2S9HtC2NOWwOFX35cy1QGT+pxCICOFi+tNkiEouNKwz6KvDwORkn1fzJvlgGVtD21urEAao/9G9UYCETgKk7eoUMAr7m4ManAppq7zMuEuaeF2jfBXwpqkPspXzkoeH4SwJVEJ+QaRdXLG3JmHZCsMgrzf+wbi6C3VxrW489UqKDber+iP8SYYCf3ZDU0yUFS1wweSSJf0A608J3RwwCPnhoAcyt21SfYFDOrYpMlvUIIyhxtPnhWlzwvNMXQ5TXjxMru87NQQsyXORTxlBgOGPNa9GF0Kt83ohbnHPjKZeodRDVmcrw4Kw05DIfSTEF6QpNmFJjjXgQ==");
            //主体资料   也是二级节点
            ObjectNode secondNodeSubject = rootNode.putObject("subject_info");
            secondNodeSubject.put("subject_type", "SUBJECT_TYPE_ENTERPRISE");    //主体类型
            secondNodeSubject.putObject("business_license_info")         //营业执照
                    .put("license_copy", "4NySZW6V1IKaceiyVAwBfJ_DmWC5P4XQzIhR9Jqpmw8AxkFMXpg1MksJpb0BsBEqIlsq1XwRb5naBYJqTNRLX_yYJMsjHYy3Ckpc5DSoqbg")
                    .put("license_number", "913101017456044662")
                    .put("merchant_name", "上海浦江物业有限公司")
                    .put("legal_person", "傅其昌");
            ObjectNode threedNodeSubject = secondNodeSubject.putObject("identity_info")         //法定人身份证证件
                    .put("id_doc_type", "IDENTIFICATION_TYPE_IDCARD");
            threedNodeSubject.putObject("id_card_info")
                                .put("id_card_copy","4NySZW6V1IKaceiyVAwBfHnqhgnAmSw_lVswOgPFeJo7Mm2XYamfrTtoERpUjNL2h-igea3sJ2kMfm74s4VFCE-Gh7Ac26IHdxv2yLjoKtU")
                                .put("id_card_national","4NySZW6V1IKaceiyVAwBfBL3CIoH30AiCltH-PjfmGX29MI9IV8lgZpdQh9onD60FF7JLjU794joNO99qjTOUUayVLu8O1fj7vcgKUOAoaU")
                                .put("id_card_name","NDUvLPrieluK6rcdnrjU6AyLIgM39LkXg8uzk1CipV6hV8YagU9OOORrfC62RcyzBixnGLPsxBxgifuaE6Y0J31XoWXaoeXUyAKvFJpk1bzbvXkbTwQ9dGJ3TIjoqh2+F41/0+4DyjeRtAf88BYTG8BpW4i5xWm834rNYlv7MJsK4TnqYyazIKex6QZfZH1qLKumlXiYFpkLadEhtgawlWcsoirHTcMA8BKWVkMcERCgSe6XdcL+txB0k3/6PWus/2rIdWuG2TsbbE1zpgZ9KjLgwYkaJfzUjkG1PkAgjgmR/z0HvNXEY6GvLCqmlsRWCPfV0xSpeDWBoVhGEVIUnw==")
                                .put("id_card_number","a9qTGG3a08BVDLEd4CJsd25rpEvbHyyvHjd1DFHSZMf6eAYY5hespDwt2wLwMg9dVAmmNj2k7yo+kvKvagAIUagAqKef1CWSxYFcKQGXyd4ck5MZwVQXGyjkpZAIiwfEx31CJvu74V4Tl1TMFdHMPWRpiwyFgmloJJDP9F7dRirzklRsvXnSoRT16tKFJYJwkwoBdHTGkoU6A5STNWzzYtP9XJvPaA0WPh0bmep2FnVpNN38KdpD24MosrOt8LxXepVkDSgE8Gw03B0p2MZ9Co2awNwaeRpnU2SovtJI05GdIYziCPzSZsZWFCv/rPPIsFshJVYTys2O7YNU+hYgaw==")
                                .put("card_period_begin","2011-05-17")
                                .put("card_period_end","长期");
            threedNodeSubject.put("owner",true);

            //经营资料   经营资料的二级节点  secondNode_sales_info
            ObjectNode secondNode_sales_info = rootNode.putObject("business_info")
                        .put("merchant_shortname","上海浦江物业")
                        .put("service_phone","86-21-63333599")
                        .putObject("sales_info");
            secondNode_sales_info.putArray("sales_scenes_type").add("SALES_SCENES_MINI_PROGRAM");
            secondNode_sales_info.putObject("mini_program_info")
                        .put("mini_program_appid","wxbd21653c15549969")
                        .putArray("mini_program_pics")
                        .add("4NySZW6V1IKaceiyVAwBfEkmyjjFwYyMVSR9JqHySnAunTOPrrx0tABNLB77JUkv820ug7h7I7yhkNzF_VNtNf-tD_xYoMYU5rGpNAj_0Ko");

            rootNode.putObject("settlement_info")       //结算规则
                        .put("settlement_id","716")
                        .put("qualification_type" ,"餐饮");
            rootNode.putObject("bank_account_info")     //结算银行账户
                        .put("bank_account_type","BANK_ACCOUNT_TYPE_CORPORATE")
                        .put("account_name","rhWHMUsHIpO3FJ7F5VzFqAeFeALBGxsM8+kosd5JhYClP2crEccJEc8HkOtv7AfsfLvsgYfYuD3vnuK1cnrkP6H74FzGgUq98tIhzulB4I+HItFJl97Io5FEgecxjod22WiIVmSor8jtLHZYXEMw+ZtR1z/m9feqRAb2dR8V3Y9Ph7iJBoNWETmx5vCnpXHs75K6Ej1g4V9M6TuWFzZCSRLc0nHLbo/qfDtQUAJgxKz09NAkIVatQL9swEKI91tNufP7MCYOMJMn8kkOYGEej/j61407E8wHniEMwAbVVg/j2UW5agjhsd+LlUli6JjBuOmRlxsfBaibTKUSDkJDTg==")
                        .put("account_bank","其他银行")
                        .put("bank_address_code","310115")
                        .put("bank_name","上海浦东发展银行金汇支行")
                        .put("account_number","FIR94eQmZdkQdU3qS62vlEq1lR6+bFXzUB4VOZ+c/8ffrEZLgbn23v8buhaJvm+i90oxSuFElflvevhED7LOiCY6OjfHp7K3Yi99orjaoufMA9iUKMTCW0AC8mFqNVjosd6NmbX4WIFvqUpcYyNaY7bznj4n9TjZuYwJQTDiq+yyDhwFeBteLD1W7Y/rsVf7Ejd/ZokHnavM3S0u/uh13+BOpcIrg4iYNANgLBlCSSh7lQSRkJCjdvfnQQK6d1BigGrwqA8i134jwvuRJhwALvsWBSdawX/T6KEvRQ/afx5PiU0B33iygu9X9Bj5pFiLve7Z49ZzolddlWkv9e0trw==");

            String str = rootNode.toString();
            StringEntity reqEntity = new StringEntity(str, APPLICATION_JSON);
            httpPost.setEntity(reqEntity);
            //发送请求
            response = httpClient.execute(httpPost);
            int statusCode = response.getStatusLine().getStatusCode();
            bodyAsString = EntityUtils.toString(response.getEntity());
            System.out.println("===code:"+statusCode);
            System.out.println(bodyAsString);

        } catch (Exception e) {
           // e.printStackTrace();
            System.out.println(e);
        }
        return ResponseEntity.ok(bodyAsString);
    }

    /**
     * @Decription 使用微信平台证书公钥对敏感信息加密
     * 商户进件
     * @Param   null
     * @Return  java.lang.String
     * @Author  lmh
     * @Date    2021/12/28 9:59
     */
    @RequestMapping("/rsaEncrypt")
    public static String rsaEncryptOAEP(String message) {
        byte[] cipherdata = null;
        try {
//            String privateKey = "F262569B8D2DE74893C374AF6247EC17";
//            PrivateKey merchantPrivateKey = PemUtil.loadPrivateKey(
//                        new ByteArrayInputStream(privateKey.getBytes("utf-8")));
//            X509Certificate verifier = (X509Certificate)new ScheduledUpdateCertificatesVerifier(
//                    new WechatPay2Credentials("1552062431", new PrivateKeySigner("7FAAF5C816F8DE7BCB5B247D4B60B5A04446E803",merchantPrivateKey)),
//                    "d6f54dc2e6dc46a58e0eb9948beb30df".getBytes(StandardCharsets.UTF_8));
            File file = new File("E:\\wxcertificate\\wechatpay_7D200113C91B6FF28A083D163B2005BA11F4BB57.pem");
            InputStream inStream =  new FileInputStream(file);
            X509Certificate certificate = X509Certificate.getInstance(inStream);

            Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-1AndMGF1Padding");
            try {
                cipher.init(Cipher.ENCRYPT_MODE, certificate.getPublicKey());
            } catch (InvalidKeyException e) {
                e.printStackTrace();
            }

            byte[] data = new byte[0];
            data = message.getBytes("utf-8");
            cipherdata = cipher.doFinal(data);

        }catch (Exception e) {
            e.printStackTrace();
        }
        return Base64.getEncoder().encodeToString(cipherdata);
    }

    @PostMapping("/getMediaID")
    public String uploadImageTest(String filepath) {
        String s = null;
        try {
            CloseableHttpClient httpClient = this.getHttpClient();
            URI uri = new URI("https://api.mch.weixin.qq.com/v3/merchant/media/upload");
            String filePath = filepath;
            File file = new File(filePath);
            //带参数的try(){}，表示try块退出的时候，会自动关闭流资源
            try (FileInputStream fileIs = new FileInputStream(file)) {
                String sha256 = DigestUtils.sha256Hex(fileIs);
                try (InputStream is = new FileInputStream(file)) {
                    WechatPayUploadHttpPost request = new WechatPayUploadHttpPost.Builder(uri)
                            .withImage(file.getName(), sha256, is)
                            .build();
                    CloseableHttpResponse response = httpClient.execute(request);
                    HttpEntity entity = response.getEntity();
                    s = EntityUtils.toString(entity);
                }
            }
        }catch (IOException e) {
            e.printStackTrace();
        }catch (URISyntaxException e) {
            e.printStackTrace();
        }
        return s;
    }

}
